/* socket.h : dgnsc socket
 * Copyright (C) 2009-2011 drangon <drangon.zhou@gmail.com>
 * 2009-05
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef INCLUDED_DGNSC_SOCKET_H
#define INCLUDED_DGNSC_SOCKET_H

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

#define DGN_IP_LEN	46  // ipv6 : 46, ipv4 : 16

#define DGN_SOCK_DEFAULT_TIMEOUT_MS	3000

// <0> util function, resolve domain
int dgn_sock_host_to_ip( const char * host, char ip[DGN_IP_LEN] ); // host can = ip

typedef struct dgn_sock_st * dgn_sock_t;

enum dgn_sock_connect_result_e {
	DGN_SOCK_CONNECT_UNKNOWN = 0,
	DGN_SOCK_CONNECT_FAILED,
	DGN_SOCK_CONNECT_TRYING,
	DGN_SOCK_CONNECT_OK,
};

// <1> socket create
dgn_sock_t dgn_sock_init();
dgn_sock_t dgn_sock_init_accept( dgn_sock_t listen_sk );
void dgn_sock_fini( dgn_sock_t sk );

// set timeout to 0 can interrupt current operation
int dgn_sock_set_timeout( dgn_sock_t sk, int timeout_ms );
// user data
void * dgn_sock_get_tag( dgn_sock_t sk );
void dgn_sock_set_tag( dgn_sock_t sk, void * tag );

int dgn_sock_tcp_svr( dgn_sock_t sk, const char * listen_host, int port );
enum dgn_sock_connect_result_e dgn_sock_tcp_connect( dgn_sock_t sk, const char * remote_host, int port );
int dgn_sock_udp( dgn_sock_t sk, const char * bind_host, int port );

// only call this when dgn_sock_tcp_connect() return DGN_SOCK_CONNECT_TRYING
// then use this function to check result again
enum dgn_sock_connect_result_e dgn_sock_connect_check( dgn_sock_t sk );

// <2> socket infomation
int dgn_sock_local_addr( dgn_sock_t sk, char ip[DGN_IP_LEN], int * port );
int dgn_sock_remote_addr( dgn_sock_t sk, char ip[DGN_IP_LEN], int * port );


// <3> socket data transport, poll/send/recv
enum {
	DGN_POLLIN = 1,
	DGN_POLLOUT = 2,
};

// return > 0 : has event; = 0 : timeout; < 0 : error
int dgn_sock_poll( dgn_sock_t sk, int want_evt, int * ret_evt );
// max num 1024, return > 0 : has event socket num; = 0 : timeout; < 0 : error
int dgn_sock_pollex( int num, dgn_sock_t * skarr, const int * want_evt, int * ret_evt, volatile int * timeout_ms );

// return > 0 : data sent; = 0 : timeout; < 0 : error and send nothing
int dgn_sock_send( dgn_sock_t sk, const char * buf, int len );
// return > 0 : data recved; = 0 : timeout; < 0 : error and recv nothing
int dgn_sock_recv( dgn_sock_t sk, char * buf, int minlen, int maxlen );

int dgn_sock_sendto( dgn_sock_t sk, const char * buf, int len, const char * remote_host, int port );
int dgn_sock_recvfrom( dgn_sock_t sk, char * buf, int len, char remote_ip[DGN_IP_LEN], int * port );

#ifdef __cplusplus
}
#endif // __cplusplus

#endif // INCLUDED_DGNSC_SOCKET_H

